Update from Josh. Get the extension list dynamically instead of from
authorrobertl <robertl@f51c46e8-681c-474f-0cfe-069cfd0219fb>
Wed, 4 Dec 2002 17:44:45 +0000 (17:44 +0000)
committerrobertl <robertl@f51c46e8-681c-474f-0cfe-069cfd0219fb>
Wed, 4 Dec 2002 17:44:45 +0000 (17:44 +0000)
internal table.

gpsbabel/win32/gpsbabelfront_mainform.dfm
gpsbabel/win32/gpsbabelfront_mainform.pas

index 6abfda6e8c4a63c097cc1e637a17c144bf79e159..7721ba5c308622b43219254b096d1be5e5ca136b 100644 (file)
@@ -3,7 +3,7 @@ object FormGPSBabelFront: TFormGPSBabelFront
   Top = 103
   BorderStyle = bsDialog
   Caption = 'GPSBabel GUI Frontend'
-  ClientHeight = 212
+  ClientHeight = 312
   ClientWidth = 369
   Color = clBtnFace
   Font.Charset = DEFAULT_CHARSET
@@ -16,12 +16,12 @@ object FormGPSBabelFront: TFormGPSBabelFront
   OnCreate = FormCreate
   DesignSize = (
     369
-    212)
+    312)
   PixelsPerInch = 96
   TextHeight = 13
   object Label1: TLabel
     Left = 8
-    Top = 192
+    Top = 292
     Width = 250
     Height = 13
     Anchors = [akLeft, akBottom]
@@ -43,11 +43,32 @@ object FormGPSBabelFront: TFormGPSBabelFront
   end
   object Bevel1: TBevel
     Left = -3
-    Top = 185
+    Top = 285
     Width = 380
     Height = 2
     Anchors = [akLeft, akBottom]
   end
+  object Label4: TLabel
+    Left = 16
+    Top = 104
+    Width = 35
+    Height = 13
+    Caption = 'Format:'
+  end
+  object Label5: TLabel
+    Left = 16
+    Top = 40
+    Width = 35
+    Height = 13
+    Caption = 'Format:'
+  end
+  object Label6: TLabel
+    Left = 8
+    Top = 168
+    Width = 33
+    Height = 13
+    Caption = 'Result:'
+  end
   object comboInput: TComboBox
     Left = 64
     Top = 40
@@ -82,7 +103,7 @@ object FormGPSBabelFront: TFormGPSBabelFront
   end
   object btnProcess: TButton
     Left = 288
-    Top = 152
+    Top = 136
     Width = 75
     Height = 25
     Caption = 'Process'
@@ -115,12 +136,21 @@ object FormGPSBabelFront: TFormGPSBabelFront
     TabOrder = 4
     OnClick = btnOutputClick
   end
+  object memoStdErr: TMemo
+    Left = 64
+    Top = 168
+    Width = 297
+    Height = 113
+    Color = clBtnHighlight
+    ReadOnly = True
+    TabOrder = 8
+  end
   object OpenDialogInput: TOpenDialog
-    Left = 80
-    Top = 8
+    Left = 248
+    Top = 192
   end
   object SaveDialogOutput: TSaveDialog
-    Left = 80
-    Top = 72
+    Left = 248
+    Top = 240
   end
 end
index 7dd7a9d94a3b5ba2e5789d0ba6a2da0a63774c73..4507e12ab2f4bd6b25e8de2dde02581bf3e88f0f 100644 (file)
@@ -1,6 +1,6 @@
 {
 
-               Copyright (C) 2002 Josh M. McKee, geo@mrsnazz.com
+    Copyright (C) 2002 Josh M. McKee, mrsnazz@users.sourceforge.net
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
 
 }
 
+{
+    1.0.0   JMc   First release
+    1.0.1   JMc   - Switched to using AddFormat for populating the formats table
+                  - Updated formats table to include currently supported formats
+                  - Switched to using CreateProcess rather than WinExec, so that
+                    we can display data from stderr to the user.
+    1.0.2   JMc   - Added LoadFormats to call the new -^ switch, to dynamically
+                    load the supported formats from gpsbabel.exe.
+}
+
 unit gpsbabelfront_mainform;
 
 interface
@@ -26,12 +36,9 @@ uses
   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
   Dialogs, ExtCtrls, StdCtrls;
 
-const
-       FormatCount = 18;
-
 type
-       TFormat = record
-       sType:string; // type to be passed to GPSBabel
+  TFormat = record
+    sType:string; // type to be passed to GPSBabel
     sExt:string;  // default file extension
     sDesc:string; // description of format
   end;
@@ -51,15 +58,20 @@ type
     btnOutput: TButton;
     OpenDialogInput: TOpenDialog;
     SaveDialogOutput: TSaveDialog;
+    Label4: TLabel;
+    Label5: TLabel;
+    memoStdErr: TMemo;
+    Label6: TLabel;
     procedure FormCreate(Sender: TObject);
     procedure btnInputClick(Sender: TObject);
     procedure btnOutputClick(Sender: TObject);
     procedure btnProcessClick(Sender: TObject);
-  private
-    { Private declarations }
   public
-    { Public declarations }
-    formats:array[0..FormatCount-1] of TFormat;
+    formats:array of TFormat;
+    nFormatCount:integer;
+
+    procedure LoadFormats;
+    procedure AddFormat(sType,sExt,sDesc:string);
 
     procedure PopulateCombos;
     procedure PopulateDialogs;
@@ -72,29 +84,40 @@ implementation
 
 {$R *.dfm}
 
+procedure TFormGPSBabelFront.AddFormat(sType,sExt,sDesc:string);
+begin
+  SetLength(formats,nFormatCount+1);
+
+  formats[nFormatCount].sType := sType;
+  formats[nFormatCount].sExt := sExt;
+  formats[nFormatCount].sDesc := sDesc;
+
+  inc(nFormatCount);
+end;
+
 procedure TFormGPSBabelFront.PopulateCombos;
 var
-       i:integer;
+  i:integer;
 begin
-       for i:=0 to FormatCount-1 do begin
-       comboInput.items.add(formats[i].sDesc);
+  for i:=0 to nFormatCount-1 do begin
+    comboInput.items.add(formats[i].sDesc);
     comboOutput.items.add(formats[i].sDesc);
   end;
 end;
 
 procedure TFormGPSBabelFront.PopulateDialogs;
 var
-       i:integer;
+  i:integer;
 begin
-       OpenDialogInput.Filter := '';
+  OpenDialogInput.Filter := '';
   SaveDialogOutput.Filter := '';
-       for i:=0 to FormatCount-1 do begin
-               if (formats[i].sExt<>'') then begin
-       OpenDialogInput.Filter := OpenDialogInput.Filter + formats[i].sDesc + ' (*.' +
-               formats[i].sExt + ')|*.' + uppercase(formats[i].sExt) + '|';
+  for i:=0 to nFormatCount-1 do begin
+    if (formats[i].sExt<>'') then begin
+      OpenDialogInput.Filter := OpenDialogInput.Filter + formats[i].sDesc + ' (*.' +
+        formats[i].sExt + ')|*.' + uppercase(formats[i].sExt) + '|';
 
-                       SaveDialogOutput.Filter := SaveDialogOutput.Filter + formats[i].sDesc + ' (*.' +
-               formats[i].sExt + ')|*.' + uppercase(formats[i].sExt) + '|';
+      SaveDialogOutput.Filter := SaveDialogOutput.Filter + formats[i].sDesc + ' (*.' +
+        formats[i].sExt + ')|*.' + uppercase(formats[i].sExt) + '|';
     end;
   end;
 
@@ -104,112 +127,256 @@ end;
 
 procedure TFormGPSBabelFront.FormCreate(Sender: TObject);
 begin
-       formats[0].sType := 'geo';
-  formats[0].sExt := 'loc';
-  formats[0].sDesc := 'Geocaching.com .loc';
-       formats[1].sType := 'gpsman';
-  formats[1].sExt := '';
-  formats[1].sDesc := 'GPSman';
-       formats[2].sType := 'gpx';
-       formats[2].sExt := 'gpx';
-  formats[2].sDesc := 'GPX XML';
-  formats[3].sType := 'magellan';
-  formats[3].sExt := '';
-  formats[3].sDesc := 'Magellan protocol';
-       formats[4].sType := 'mapsend';
-  formats[4].sExt := '';
-  formats[4].sDesc := 'Magellan Mapsend';
-  formats[5].sType := 'pcx';
-  formats[5].sExt := 'pcx';
-  formats[5].sDesc := 'Garmin PCX5';
-  formats[6].sType := 'mapsource';
-  formats[6].sExt := '';
-  formats[6].sDesc := 'Garmin Mapsource';
-  formats[7].sType := 'gpsutil';
-  formats[7].sExt := '';
-  formats[7].sDesc := 'gpsutil';
-  formats[8].sType := 'tiger';
-  formats[8].sExt := '';
-  formats[8].sDesc := 'U.S. Census Bureau Tiger Mapping Service';
-  formats[9].sType := 'csv';
-  formats[9].sExt := 'csv';
-  formats[9].sDesc := 'Comma separated values';
-  formats[10].sType := 'dna';
-  formats[10].sExt := 'dna';
-  formats[10].sDesc := 'Navitrak DNA marker format';
-  formats[11].sType := 'psp';
-  formats[11].sExt := 'psp';
-  formats[11].sDesc := 'MS PocketStreets 2002 Pushpin';
-       formats[12].sType := 'cetus';
-  formats[12].sExt := 'pdb';
-  formats[12].sDesc := 'Cetus for Palm/OS';
-  formats[13].sType := 'gpspilot';
-  formats[13].sExt := '';
-  formats[13].sDesc := 'GPSPilot Tracker for Palm/OS';
-  formats[14].sType := 'garmin';
-  formats[14].sExt := '';
-  formats[14].sDesc := 'Garmin serial protocol';
-       formats[15].sType := 'mxf';
-  formats[15].sExt := 'mxf';
-  formats[15].sDesc := 'MapTech Exchange Format';
-       formats[16].sType := 'holux';
-  formats[16].sExt := 'wpo';
-  formats[16].sDesc := 'Holux (gm-100) .wpo Format';
-       formats[17].sType := 'ozi';
-  formats[17].sExt := 'ozi';
-  formats[17].sDesc := 'OziExplorer Waypoint';
+  nFormatCount := 0;
 
+  // load formats from GPSBabel.exe
+  LoadFormats;
+
+  if nFormatCount = 0 then begin
+    ShowMessage('Unable to load format list from GPSBabel.exe. Default format list is being used instead.');
+
+    // add the default formats
+    AddFormat('geo','loc','Geocaching.com .loc');
+    AddFormat('gpsman','','GPSman');
+    AddFormat('gpx','gpx','GPX XML');
+    AddFormat('magellan','','Magellan protocol');
+    AddFormat('mapsend','','Magellan Mapsend');
+    AddFormat('pcx','pcx','Garmin PCX5');
+    AddFormat('mapsource','','Garmin Mapsource');
+    AddFormat('gpsutil','','gpsutil');
+    AddFormat('tiger','','U.S. Census Bureau Tiger Mapping Service');
+    AddFormat('csv','csv','Comma seperated values');
+    AddFormat('xmap','','Delorme Topo USA4/XMap Conduit');
+    AddFormat('dna','dna','Navitrak DNA marker format');
+    AddFormat('psp','psp','MS PocketStreets 2002 Pushpin');
+    AddFormat('cetus','','Cetus for Palm/OS');
+    AddFormat('gpspilot','','GPSPilot Tracker for Palm/OS');
+    AddFormat('magnav','','Magellan NAV Companion for PalmOS');
+    AddFormat('garmin','','Garmin serial protocol');
+    AddFormat('mxf','mxf','MapTech Exchange Format');
+    AddFormat('holux','wpo','Holux (gm-100) .wpo Format');
+    AddFormat('ozi','ozi','OziExplorer Waypoint');
+    AddFormat('tpg','tpg','National Geographic Topo .tpg');
+    AddFormat('tmpro','tmpro','TopoMapPro Places File');
+  end;
+
+  // Set up the dropdown lists and open/save dialog filters using the formats
   PopulateCombos;
   PopulateDialogs;
 end;
 
 procedure TFormGPSBabelFront.btnInputClick(Sender: TObject);
 var
-       sExt:string;
+  sExt:string;
   i:integer;
 begin
-       if opendialoginput.Execute then begin
-       editInput.Text := opendialoginput.filename;
+  if opendialoginput.Execute then begin
+    editInput.Text := opendialoginput.filename;
     sExt := uppercase(ExtractFileExt(editInput.text));
-               for i := 0 to FormatCount-1 do begin
-       if '.' + uppercase(formats[i].sExt) = sExt then comboInput.ItemIndex := i;
+    for i := 0 to nFormatCount-1 do begin
+      if '.' + uppercase(formats[i].sExt) = sExt then comboInput.ItemIndex := i;
     end;
   end;
 end;
 
 procedure TFormGPSBabelFront.btnOutputClick(Sender: TObject);
 var
-       sExt:string;
+  sExt:string;
   i:integer;
 begin
-       if savedialogoutput.Execute then begin
-       editOutput.Text := savedialogoutput.filename;
+  if savedialogoutput.Execute then begin
+    editOutput.Text := savedialogoutput.filename;
     sExt := uppercase(ExtractFileExt(editOutput.text));
-               for i := 0 to FormatCount-1 do begin
-       if '.' + uppercase(formats[i].sExt) = sExt then comboOutput.ItemIndex := i;
+    for i := 0 to nFormatCount-1 do begin
+      if '.' + uppercase(formats[i].sExt) = sExt then comboOutput.ItemIndex := i;
     end;
   end;
 end;
 
+procedure TFormGPSBabelFront.LoadFormats;
+var
+  sIgnoreShort:string;
+  sCmd:string;
+  f:file;
+  Buffer:array[0..255] of char;
+  hRead,hWrite:THandle;
+  StartupInfo:TStartupInfo;
+  ProcessInfo:TProcessInformation;
+  saAttr:TSecurityAttributes;
+  OutSt:TMemoryStream;
+  dwRead:DWord;
+  dwExitCode:cardinal;
+  overlapped:TOverlapped;
+  slstFormats:TStringList;
+  i:integer;
+
+  procedure ExtractFormat(sFormat:string);
+  var
+    toks:array[0..2] of string;
+    i,nTok,nLen:integer;
+  begin
+    i := 1;
+    nTok := 0;
+    toks[0] := '';
+    toks[1] := '';
+    toks[2] := '';
+    nLen := length(sFormat);
+    while ((i<=nLen) and (nTok<3)) do begin
+      if sFormat[i]=#9 then begin
+        inc(nTok);
+      end else begin
+        toks[nTok] := toks[nTok] + sFormat[i];
+      end;
+      inc(i);
+    end;
+    {showmessage(toks[0]);
+    showmessage(toks[1]);
+    showmessage(toks[2]);}
+    
+    AddFormat(toks[0],toks[1],toks[2]);
+  end;
+
+begin
+  slstFormats := TStringList.Create;
+
+  sCmd := 'GPSBabel -^';
+
+  memoStdErr.lines.clear;
+
+  saAttr.nLength := sizeof(TSECURITYATTRIBUTES);
+  saAttr.bInheritHandle := true;
+  saAttr.lpSecurityDescriptor := nil;
+
+  if not CreatePipe(hRead, hWrite,@saAttr,0) then begin
+    ShowMessage('Unable to create pipe!');
+    Exit;
+  end;
+
+  AllocConsole;
+
+  FillChar(StartupInfo,Sizeof(StartupInfo),#0);
+  StartupInfo.cb := Sizeof(StartupInfo);
+  StartupInfo.dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
+  StartupInfo.wShowWindow := SW_HIDE and SW_SHOWMINNOACTIVE;
+  StartupInfo.hStdInput := GetStdHandle(STD_INPUT_HANDLE);
+  StartupInfo.hStdOutput:= hWrite;
+  StartupInfo.hStdError := hWrite;
+
+  if not CreateProcess(nil,pchar(sCmd),nil,nil,true,CREATE_NEW_CONSOLE,nil,nil,StartupInfo,ProcessInfo) then begin
+    ShowMessage('Unable to execute GPSBabel.exe.')
+  end else begin
+    while (WaitforSingleObject(ProcessInfo.hProcess,0)) <> WAIT_OBJECT_0 do;
+
+    PeekNamedPipe(hRead,nil,0,nil,@dwRead,nil);
+
+    if dwRead>0 then begin
+      OutSt := TMemoryStream.Create;
+
+      repeat
+        if ReadFile(hRead, Buffer, 80, dwRead, nil) then begin
+          OutSt.WriteBuffer(Buffer, dwRead)
+      end;
+      until dwRead<>80;
+
+      OutSt.Seek(0,0);
+      slstFormats.LoadFromStream(OutSt);
+      for i:=0 to slstFormats.count-1 do begin
+        ExtractFormat(slstFormats[i]);
+      end;
+      OutSt.Free;
+    end else memoStdErr.lines.add('Command executed successfully.');
+  end;
+
+  CloseHandle(hRead); CloseHandle(hWrite);
+  FreeConsole;
+end;
+
 procedure TFormGPSBabelFront.btnProcessClick(Sender: TObject);
 var
-       sIgnoreShort:string;
+  sIgnoreShort:string;
   sCmd:string;
   f:file;
+  Buffer:array[0..255] of char;
+  hRead,hWrite:THandle;
+  StartupInfo:TStartupInfo;
+  ProcessInfo:TProcessInformation;
+  saAttr:TSecurityAttributes;
+  OutSt:TMemoryStream;
+  dwRead:DWord;
+  dwExitCode:cardinal;
+  overlapped:TOverlapped;
 begin
-       if cbIgnoreShort.checked then sIgnoreShort := '-s' else sIgnoreShort := '';
+  if (comboInput.ItemIndex)<0 then begin
+    ShowMessage('You must select the input file format.');
+    exit;
+  end;
+
+  if (comboOutput.ItemIndex)<0 then begin
+    ShowMessage('You must select the output file format.');
+    exit;
+  end;
+
+  if cbIgnoreShort.checked then sIgnoreShort := '-s' else sIgnoreShort := '';
 
+  // The output file must exist, or else ExtractShortPathName will not function
   if not fileexists(editoutput.text) then begin
-               system.assign(f,editoutput.text);
-               system.rewrite(f);
+    system.assign(f,editoutput.text);
+    system.rewrite(f);
     system.close(f);
   end;
 
+  // Construct the command line to execute gpsbabel.exe. ExtractShortPathName
+  // is used to reduce any "long" file/directory names in the paths down to
+  // 8.3 dos format names (this removes spaces, etc).
   sCmd := 'GPSBabel '+sIgnoreShort+' -i '+formats[comboInput.itemindex].sType+' -f '+
-       ExtractShortPathName(editInput.text)+' -o '+formats[comboOutput.itemindex].sType+' -F '+
-    ExtractShortPathName(editOutput.text) + ' > result.txt';
+    ExtractShortPathName(editInput.text)+' -o '+formats[comboOutput.itemindex].sType+' -F '+
+    ExtractShortPathName(editOutput.text);
+
+  memoStdErr.lines.clear;
+
+  saAttr.nLength := sizeof(TSECURITYATTRIBUTES);
+  saAttr.bInheritHandle := true;
+  saAttr.lpSecurityDescriptor := nil;
+
+  if not CreatePipe(hRead, hWrite,@saAttr,0) then begin
+    ShowMessage('Unable to create pipe!');
+    Exit;
+  end;
+
+  AllocConsole;
+
+  FillChar(StartupInfo,Sizeof(StartupInfo),#0);
+  StartupInfo.cb := Sizeof(StartupInfo);
+  StartupInfo.dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
+  StartupInfo.wShowWindow := SW_HIDE and SW_SHOWMINNOACTIVE;
+  StartupInfo.hStdInput := GetStdHandle(STD_INPUT_HANDLE);
+  StartupInfo.hStdOutput:= hWrite;
+  StartupInfo.hStdError := hWrite;
+
+  if not CreateProcess(nil,pchar(sCmd),nil,nil,true,CREATE_NEW_CONSOLE,nil,nil,StartupInfo,ProcessInfo) then begin
+    ShowMessage('Unable to execute GPSBabel.exe.')
+  end else begin
+    while (WaitforSingleObject(ProcessInfo.hProcess,0)) <> WAIT_OBJECT_0 do;
+
+    PeekNamedPipe(hRead,nil,0,nil,@dwRead,nil);
+
+    if dwRead>0 then begin
+      OutSt := TMemoryStream.Create;
+
+      repeat
+        if ReadFile(hRead, Buffer, 80, dwRead, nil) then begin
+          OutSt.WriteBuffer(Buffer, dwRead)
+      end;
+      until dwRead<>80;
+
+      OutSt.Seek(0,0);
+      memoStdErr.lines.LoadFromStream(OutSt);
+      OutSt.Free;
+    end else memoStdErr.lines.add('Command executed successfully.');
+  end;
 
-       WinExec(pchar(sCmd),SW_SHOW);
+  CloseHandle(hRead); CloseHandle(hWrite);
+  FreeConsole;
 end;
 
 end.